/**
 * FileUtil.java
 * com.ebook.util
 * Copyright (c) 2013, 北京博观知翼有限公司版权所有.
*/

package com.ebook.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.multipart.MultipartFile;


/**
 * 上传下载通用组件
 * @author    潘吉友
 * @Date	 2013-3-8 	 
 */
public class FileUtil {
	
	private static Log logger = LogFactory.getLog(FileUtil.class);
	
	public static List<String> fileNameList = new ArrayList<String>();
	
	public static List<File> fileList = new ArrayList<File>();
	
	/**
	 * 将文件写入到指定文件内
	 * @param file 要写的文件
	 * @param toFilePath 准备写入文件的路径
	 * @return true：成功；false：失败
	 */
	public static boolean writeTo(MultipartFile file, String toFilePath) {
		try {
			logger.info("writeto: "+toFilePath);
			File outfile = new File(toFilePath);
			if (!outfile.exists()){
				if (!outfile.createNewFile()){
					logger.error("创建文件失败");
					return false;
				}
			}	
			FileOutputStream fs = new FileOutputStream(outfile);
			byte[] buffer = new byte[1024 * 1024];
			int bytesum = 0;
			int byteread = 0;
			InputStream stream = file.getInputStream();
			while ((byteread = stream.read(buffer)) != -1) {
				bytesum += byteread;
				fs.write(buffer, 0, byteread);
				fs.flush();
			}
			fs.close();
			stream.close();
		} catch (Exception e) {
			logger.error("文件操作错误" + e.getMessage());
			return false;
		}
		return true;
	}
	
	public static boolean writeToByPath(String fromFilePath, String toFilePath) {
		try {
			logger.info("writefrom: "+fromFilePath);
			InputStream stream = new FileInputStream(new File(fromFilePath));
			
			logger.info("writeto: "+toFilePath);
			File outfile = new File(toFilePath);
			if (!outfile.exists()){
				if (!outfile.createNewFile()){
					logger.error("创建文件失败");
					return false;
				}
			}	
			OutputStream fs = new FileOutputStream(outfile);
			byte[] buffer = new byte[1024 * 1024];
			int bytesum = 0;
			int byteread = 0;
			
			while ((byteread = stream.read(buffer)) != -1) {
				bytesum += byteread;
				fs.write(buffer, 0, byteread);
				fs.flush();
			}
			fs.close();
			stream.close();
		} catch (Exception e) {
			logger.error("文件操作错误",e);
			return false;
		}
		return true;
	}


	/**
	 * 文件下载功能
	 * @param filePath_Name  要下载的文件的路径	
	 * @param request   
	 * @param response
	 * @return true：成功，false：失败
	*/
	public static boolean downloadZip(String filePath_Name, HttpServletRequest request, HttpServletResponse response) {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		logger.info("downLoadPath:"+filePath_Name);
		try {
			File file = new File(filePath_Name);
			if (!file.exists()) {
				logger.error("file is not exists!");
				return false;
			}
			long fileLength = file.length();
			request.setCharacterEncoding("UTF-8");
			response.setContentType("text/html;charset=utf-8");
			response.setContentType("application/x-msdownload;");
			response.setHeader("Content-disposition",
					"attachment; filename=" + new String(file.getName().getBytes("utf-8"), "ISO8859-1"));
			response.setHeader("Content-Length", String.valueOf(fileLength));
			bis = new BufferedInputStream(new FileInputStream(file));
			bos = new BufferedOutputStream(response.getOutputStream());
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
			return true;
		} catch (Exception e) {
			logger.error("文件下载异常！" + e.getMessage());
		} finally {
			if (bis != null)
				try {
					bis.close();
				} catch (IOException e) {
					logger.error("输入流关闭失败！");
				}
			if (bos != null)
				try {
					bos.close();
				} catch (IOException e) {
					logger.error("输出流关闭失败！");
				}
		}
		// 走到这里说明下载失败
		return false;
	}
		
	/**
	 * 文件下载(断点续传)功能
	 * @param filePath_Name  要下载的文件的路径	
	 * @param request   
	 * @param response
	 * @return true：成功，false：失败
	*/
	public static boolean continueToDownload(String filePath_Name, HttpServletRequest request, HttpServletResponse response) {
		logger.info("download address:"+filePath_Name);
		String range = request.getHeader("Range");
		BufferedInputStream bis =null;
		OutputStream os = null;
		try {
			File file = new File(filePath_Name);
			if (!file.exists()) {
				logger.error("download file is not exists!");
				return false;
			}
			response.reset();
			response.setContentType("application/dmg");
			response.setHeader("Accept-Ranges", "bytes");
			response.setHeader("Content-Disposition", "attachment; filename="
					+ new String(file.getName().getBytes("utf-8"), "ISO8859-1"));
			response.setHeader("Content-Length", file.length() + "");
			os = response.getOutputStream();
			logger.info("range:"+range);
			FileInputStream fis = new FileInputStream(file);
			byte[] bytes = new byte[1024];
			if (range != null) {
				range = range.substring("bytes=".length(), range.length() - 1);
				long start = Long.parseLong(range);
				fis.skip(start);
				long l = file.length();
				String contentRange = new StringBuffer("bytes ").append(start)
						.append("-").append(l - 1).append("/").append(l)
						.toString();
				response.setHeader("Content-Range", contentRange);
				response
						.setHeader("Content-Length", file.length() - start + "");
				response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
			}
			bis = new BufferedInputStream(fis);
			int len = 0;
			while ((len = bis.read(bytes)) > 0) {
				os.write(bytes, 0, len);
			}
			bis.close();
			os.flush();
			os.close();
			return true;
		} catch (Exception e) {
			logger.info("Interruption position:"+range);
			return false;
		}finally{
			if(bis != null){
				try {
					bis.close();
				} catch (IOException e) {
				}
				bis = null;
			}
			if(os !=null){
				try {
					os.close();
				} catch (IOException e) {
				}
				os = null;
			}
		}
	}
	
	/**
	* 获取路径目录下所有相应后缀名的文件路径
	* @param path 文件路径
	* @param suffix 后缀名
	* @param isdepth 是否遍历子目录
	* @return 文件路径的链表
	*/
	public static List<String> getListFiles(String path, String suffix, boolean isdepth){
	   File file = new File(path);
	   List<String> list = FileUtil.listFile(file ,suffix, isdepth);
	   StringBuilder message = new StringBuilder();
	   if(list.isEmpty()){
		   message.append("在\"").append(path).append("\"目录下没有后缀为 ").append(suffix).append(" 的文件。");
	   }else{
	    message.append("在\"").append(path).append("\"目录下符合后缀为  ").
	    append(suffix).append(" 的文件数：").append(list.size()).append("\n");   
	    for (Iterator<String> i = list.iterator(); i.hasNext();){
	     String temp = i.next();
	     message.append(temp).append("\n");
	    }
	    logger.info(message);
//	    appendMethod("C:/Users/TechKno001/Desktop/tt/menu.txt",message.toString());
	   }
	   return list;
	}
	
	/**
	 * 遍历文件目录的子文件，返回符合条件的文件链表<br/>
	 * if (suffix==null) 返回所有文件
	 * @param f 文件
	 * @param suffix 后缀名
	 * @param isdepth 是否遍历子目录(true:遍历；false:不遍历)
	 * @return 文件链表
	*/
	private static List<String> listFile(File f, String suffix, boolean isdepth){
		   //是目录，同时需要遍历子目录
		   if (f.isDirectory() && isdepth == true){
		    File[] t = f.listFiles();
		    for (int i = 0; i < t.length; i++){
		     listFile(t[i], suffix, isdepth);
		    }
		   }else{
		    String filePath = f.getAbsolutePath();		   
		    if(suffix !=null){
		     int begIndex = filePath.lastIndexOf(".");//最后一个.(即后缀名前面的.)的索引
		     String tempsuffix = "";
		     if(begIndex != -1){//防止是文件但却没有后缀名结束的文件
		      tempsuffix = filePath.substring(begIndex + 1, filePath.length());
		     }
		     if(tempsuffix.equals(suffix)){
		      fileNameList.add(filePath);
		     }
		    }else{
		     //后缀名为null则为所有文件
		     fileNameList.add(filePath);
		    }
		   }	  
		   return fileNameList;
		}
	
	/**
	* 已追加的方式向文件中写数据
	* @param fileName 文件路径名
	* @param content  要写的内容
	*/
	public static void appendMethod(String fileName, String content)
	{
	    try{
	     //打开一个写文件器，构造函数中的第二个参数true表示以追加形式写文件
	     FileWriter writer = new FileWriter(fileName, true);
	     writer.write(content + "\r\n");
	     writer.close();
	    }catch (IOException e) {
	    logger.error(e);
	    }
	} 
}
